using System;
using System.Collections;
using System.Html;
using System.Runtime.CompilerServices;
using Awaiter;
using Nsb.Classes;
using ThemeChain;
using jQueryApi;

namespace Yoshi.Classes
{
    public delegate bool HelpTestDelegate();

    [IgnoreNamespace]
    public class Help : Await
    {
        private readonly jQueryObject _domAnchor;
        public string Message;
        private Actor _actor;

        public Help(jQueryObject domAnchor)
        {
            _domAnchor = domAnchor;
        }

        public bool IsAlive()
        {
            return _domAnchor.Is(":visible");
        }


        [AlternateSignature]
        public extern Help When(HelpTestDelegate test, Action doIt);

        public Help When(HelpTestDelegate test, Dictionary template)
        {
            return (Help) AddDl(
                delegate
                {
                    int tmr = 0;
                    tmr = AwaitTimer.SetInterval(
                        delegate
                        {
                            if (IsAlive())
                            {
                                if (test())
                                {
                                    // ReSharper disable AccessToModifiedClosure
                                    Window.ClearInterval(tmr);
                                    // ReSharper restore AccessToModifiedClosure
                                    if (Type.GetScriptType(template) == "function")
                                    {
                                        Action fn = (Action) (object) template;
                                        fn();
                                    }
                                    else
                                    {
                                        GenTemplate(template);
                                    }
                                    Done();
                                }
                            }
                            else
                            {
                                // ReSharper disable AccessToModifiedClosure
                                Window.ClearInterval(tmr);
                                // ReSharper restore AccessToModifiedClosure
                            }
                        }, 13);
                });
        }

        [AlternateSignature]
        public extern Help After(int time, Action doIt);

        public Help After(int time, Dictionary template)
        {
            return (Help) Sleep(time).AddDl(
                delegate
                {
                    if (IsAlive())
                    {
                        if (Type.GetScriptType(template) == "function")
                        {
                            Action fn = (Action) (object) template;
                            fn();
                        }
                        else
                        {
                            GenTemplate(template);
                        }
                    }
                    Done();
                });
        }

        [AlternateSignature]
        public extern Help Every(int time, Action doIt);

        public Help Every(int time, Dictionary template)
        {
            return (Help) AddDl(
                delegate
                {
                    int tmr = 0;
                    tmr = AwaitTimer.SetInterval(
                        delegate
                        {
                            if (IsAlive())
                            {
                                if (Type.GetScriptType(template) == "function")
                                {
                                    Action fn = (Action) (object) template;
                                    fn();
                                }
                                else
                                {
                                    GenTemplate(template);
                                }
                            }
                            else
                            {
                                // ReSharper disable AccessToModifiedClosure
                                Window.ClearInterval(tmr);
                                // ReSharper restore AccessToModifiedClosure
                            }
                        }, time);
                    Done();
                });
        }

        private void GenTemplate(Dictionary template)
        {
            if (_actor != null)
                Destroy();
            _actor = new Actor();
            jQueryObject help = jQuery.FromHtml("<div class='HelpBubble HelpZee'/>")
                .AppendTo(Document.Body)
                .AddClass((string) template["class"])
                .Html((string) template["message"] ?? Message)
                ;

            jQuery.FromHtml("<img class='LightBulb'/>")
                .AppendTo(help)
                .Attribute("src", Uri.Join(ThemeBase.MediaImgUri, "Common/LightBulb.png"))
                //.CSS(new Dictionary(
                //    "position", "absolute",
                //    "width", 32,
                //    "top", -13,
                //    "left", -1
                //    ))
                ;

            _actor.Element = help;

            jQueryPosition p = _domAnchor.Position();
            help.CSS(
                new Dictionary(
                    "top", p.Top - _actor.Element.GetOuterHeight() + Number.ParseInt(_actor.Element.GetCSS("padding-top")),
                    "left", p.Left + _domAnchor.GetOuterWidth() - _actor.Element.GetOuterWidth() - 20
                    )
                )
                ;

            _actor.SlideInAw(AsyncAw);

            if (template.ContainsKey("duration"))
            {
                AwaitTimer.SetTimeout(Hide, (int) template["duration"]);
            }
        }

        public void Reset()
        {
            Destroy();
            Commit();
        }

        public void Hide()
        {
            if (_actor != null)
            {
                jQueryObject el = _actor.Element;
                _actor = null;
                el.FadeOut(600, delegate { el.Remove(); });
            }
        }

        public void AutoDestory()
        {
            if (!IsAlive())
                Destroy();
            else
                Window.SetTimeout(AutoDestory, 13);
        }

        public void Destroy()
        {
            AwaitTimer.ClearAll();
            Hide();
        }

        public override Await Commit()
        {
            AutoDestory();
            return base.Commit();
        }
    }
}